package com.jfirer.mvc.binder.impl;

import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.mvc.binder.ContainerBinder;

import java.lang.reflect.Array;
import java.util.List;
import java.util.Map;

public class ArrayBinder2 implements ContainerBinder
{
    private String          prefix;
    private Class           ckass;
    private Class           componentType;
    private ContainerBinder nestBinder;

    public ArrayBinder2(String prefix, Class ckass)
    {
        this.prefix = prefix;
        this.ckass = ckass;
        componentType = ckass.getComponentType();
    }

    @Override
    public Object bindMulti(Map<String, String[]> map)
    {
        Object array = null;
        for (Map.Entry<String, String[]> each : map.entrySet())
        {
            String key = each.getKey();
            if (key.startsWith(prefix) && key.charAt(prefix.length()) == '[')
            {
                if (array == null)
                {
                    array = bind(key, each.getValue());
                }
                else
                {
                    array = bind(key, each.getValue(), array);
                }
            }
        }
        return array;
    }

    @Override
    public Object bind(Map<String, String> map)
    {
        Object array = null;
        for (Map.Entry<String, String> each : map.entrySet())
        {
            String key = each.getKey();
            if (key.startsWith(prefix) && key.charAt(prefix.length()) == '[')
            {
                if (array == null)
                {
                    array = bind(key, each.getValue());
                }
                else
                {
                    array = bind(key, each.getValue(), array);
                }
            }
        }
        return array;
    }

    private Object bind(String name, String[] value)
    {
        int length = prefix.length();
        if (name.charAt(length) != '[')
        {
            ReflectUtil.throwException(new IllegalArgumentException("表单属性:" + name + "转换异常"));
        }
        if (name.charAt(length + 1) == ']')
        {
            //相当于 pre[name][]  1,2,3
            if (ckass == int[].class)
            {
                int[] array = new int[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Integer.parseInt(value[i]);
                }
                return array;
            }
            else if (ckass == long[].class)
            {
                long[] array = new long[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Long.parseLong(value[i]);
                }
                return array;
            }
            else if (ckass == byte[].class)
            {
                byte[] array = new byte[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Byte.parseByte(value[i]);
                }
                return array;
            }
            else if (ckass == short[].class)
            {
                short[] array = new short[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Short.parseShort(value[i]);
                }
                return array;
            }
            else if (ckass == float[].class)
            {
                float[] array = new float[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Float.parseFloat(value[i]);
                }
                return array;
            }
            else if (ckass == double[].class)
            {
                double[] array = new double[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Double.parseDouble(value[i]);
                }
                return array;
            }
            else if (ckass == boolean[].class)
            {
                boolean[] array = new boolean[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Boolean.parseBoolean(value[i]);
                }
                return array;
            }
            else if (ckass == Integer[].class)
            {
                Integer[] array = new Integer[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Integer.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == Byte[].class)
            {
                Byte[] array = new Byte[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Byte.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == Short[].class)
            {
                Short[] array = new Short[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Short.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == Long[].class)
            {
                Long[] array = new Long[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Long.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == Float[].class)
            {
                Float[] array = new Float[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Float.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == Double[].class)
            {
                Double[] array = new Double[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Double.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == Boolean[].class)
            {
                Boolean[] array = new Boolean[value.length];
                for (int i = 0; i < array.length; i++)
                {
                    array[i] = Boolean.valueOf(value[i]);
                }
                return array;
            }
            else if (ckass == String[].class)
            {
                String[] array = value;
                return array;
            }
            else
            {
                throw new IllegalStateException(name + "这种模式和数组模式不匹配");
            }
        }
        else
        {
            return bind(name, value[0]);
        }
    }

    @Override
    public Object bind(String name, String[] value, Object container)
    {
        return bind(name, value[0], container);
    }

    @Override
    public Object bind(String name, String value, Object container)
    {
        int length = prefix.length();
        if (name.charAt(length) != '[')
        {
            ReflectUtil.throwException(new IllegalArgumentException("表单属性:" + name + "转换异常"));
        }
        if (container == null)
        {
            return bind(name, value);
        }
        else if (name.charAt(length + 1) == ']')
        {
            int    arrayLength = Array.getLength(container);
            Object newArray    = Array.newInstance(componentType, arrayLength + 1);
            System.arraycopy(container, 0, newArray, 0, arrayLength + 1);
            container = newArray;
            //相当于 pre[name][]  1,2,3
            if (ckass == int[].class)
            {
                int[] array = (int[]) container;
                array[array.length - 1] = Integer.parseInt(value);
            }
            else if (ckass == Byte[].class)
            {
                Byte[] array = (Byte[]) container;
                array[array.length - 1] = Byte.parseByte(value);
            }
            else if (ckass == Short[].class)
            {
                Short[] array = (Short[]) container;
                array[array.length - 1] = Short.parseShort(value);
            }
            else if (ckass == Long[].class)
            {
                Long[] array = (Long[]) container;
                array[array.length - 1] = Long.parseLong(value);
            }
            else if (ckass == Boolean[].class)
            {
                Boolean[] array = (Boolean[]) container;
                array[array.length - 1] = Boolean.parseBoolean(value);
            }
            else if (ckass == Float[].class)
            {
                Float[] array = (Float[]) container;
                array[array.length - 1] = Float.parseFloat(value);
            }
            else if (ckass == Double[].class)
            {
                Double[] array = (Double[]) container;
                array[array.length - 1] = Double.parseDouble(value);
            }
            else if (ckass == Character[].class)
            {
                Character[] array = (Character[]) container;
                array[array.length - 1] = value.charAt(0);
            }
            else if (ckass == Integer[].class)
            {
                Integer[] array = (Integer[]) container;
                array[array.length - 1] = Integer.valueOf(value);
            }
            else if (ckass == Byte[].class)
            {
                Byte[] array = (Byte[]) container;
                array[array.length - 1] = Byte.valueOf(value);
            }
            else if (ckass == Short[].class)
            {
                Short[] array = (Short[]) container;
                array[array.length - 1] = Short.valueOf(value);
            }
            else if (ckass == Long[].class)
            {
                Long[] array = (Long[]) container;
                array[array.length - 1] = Long.valueOf(value);
            }
            else if (ckass == Boolean[].class)
            {
                Boolean[] array = (Boolean[]) container;
                array[array.length - 1] = Boolean.valueOf(value);
            }
            else if (ckass == Float[].class)
            {
                Float[] array = (Float[]) container;
                array[array.length - 1] = Float.valueOf(value);
            }
            else if (ckass == Double[].class)
            {
                Double[] array = (Double[]) container;
                array[array.length - 1] = Double.valueOf(value);
            }
            else if (ckass == Character[].class)
            {
                Character[] array = (Character[]) container;
                array[array.length - 1] = value.charAt(0);
            }
            else if (ckass == String[].class)
            {
                String[] array = (String[]) container;
                array[array.length - 1] = value;
            }
            else
            {
                throw new IllegalStateException(name + "这种模式和数组模式不匹配");
            }
            return container;
        }
        else
        {
            int end         = name.indexOf(']', length);
            int index       = Integer.parseInt(name.substring(length + 1, end));
            int arrayLength = Array.getLength(container);
            if (index >= arrayLength)
            {
                Object newArray = Array.newInstance(componentType, index + 1);
                System.arraycopy(container, 0, newArray, 0, index + 1);
                container = newArray;
            }
            if (ckass == int[].class)
            {
                int[] array = (int[]) container;
                array[index] = Integer.parseInt(value);
            }
            else if (ckass == byte[].class)
            {
                byte[] array = (byte[]) container;
                array[index] = Byte.parseByte(value);
            }
            else if (ckass == short[].class)
            {
                short[] array = (short[]) container;
                array[index] = Short.parseShort(value);
            }
            else if (ckass == long[].class)
            {
                long[] array = (long[]) container;
                array[index] = Long.parseLong(value);
            }
            else if (ckass == boolean[].class)
            {
                boolean[] array = (boolean[]) container;
                array[index] = Boolean.parseBoolean(value);
            }
            else if (ckass == float[].class)
            {
                float[] array = (float[]) container;
                array[index] = Float.parseFloat(value);
            }
            else if (ckass == double[].class)
            {
                double[] array = (double[]) container;
                array[index] = Double.parseDouble(value);
            }
            else if (ckass == char[].class)
            {
                char[] array = (char[]) container;
                array[index] = value.charAt(0);
            }
            else if (ckass == Integer[].class)
            {
                Integer[] array = (Integer[]) container;
                array[index] = Integer.valueOf(value);
            }
            else if (ckass == Byte[].class)
            {
                Byte[] array = (Byte[]) container;
                array[index] = Byte.valueOf(value);
            }
            else if (ckass == Short[].class)
            {
                Short[] array = (Short[]) container;
                array[index] = Short.valueOf(value);
            }
            else if (ckass == Long[].class)
            {
                Long[] array = (Long[]) container;
                array[index] = Long.valueOf(value);
            }
            else if (ckass == Boolean[].class)
            {
                Boolean[] array = (Boolean[]) container;
                array[index] = Boolean.valueOf(value);
            }
            else if (ckass == Float[].class)
            {
                Float[] array = (Float[]) container;
                array[index] = Float.valueOf(value);
                return array;
            }
            else if (ckass == Double[].class)
            {
                Double[] array = (Double[]) container;
                array[index] = Double.valueOf(value);
                return array;
            }
            else if (ckass == Character[].class)
            {
                Character[] array = (Character[]) container;
                array[index] = value.charAt(0);
                return array;
            }
            else if (ckass == String[].class)
            {
                String[] array = (String[]) container;
                array[index] = value;
            }
            else
            {
                try
                {
                    Object[] array   = (Object[]) container;
                    String   subName = name.substring(end + 1);
                    generateArrayElement(subName, value, index, array);
                    return array;
                }
                catch (Exception e)
                {
                    ReflectUtil.throwException(e);
                    return null;
                }
            }
            return container;
        }
    }

    private Object bind(String name, String value)
    {
        int length = prefix.length();
        if (name.charAt(length + 1) == ']')
        {
            //相当于 pre[name][]  1,2,3
            if (ckass == int[].class)
            {
                return new int[]{Integer.parseInt(value)};
            }
            else if (ckass == byte[].class)
            {
                return new byte[]{Byte.parseByte(value)};
            }
            else if (ckass == short[].class)
            {
                return new short[]{Short.parseShort(value)};
            }
            else if (ckass == long[].class)
            {
                return new long[]{Long.parseLong(value)};
            }
            else if (ckass == boolean[].class)
            {
                return new boolean[]{Boolean.parseBoolean(value)};
            }
            else if (ckass == float[].class)
            {
                return new float[]{Float.parseFloat(value)};
            }
            else if (ckass == double[].class)
            {
                return new double[]{Double.parseDouble(value)};
            }
            else if (ckass == char[].class)
            {
                return new char[]{value.charAt(0)};
            }
            else if (ckass == Integer[].class)
            {
                return new Integer[]{Integer.valueOf(value)};
            }
            else if (ckass == Byte[].class)
            {
                return new Byte[]{Byte.valueOf(value)};
            }
            else if (ckass == Short[].class)
            {
                return new Short[]{Short.valueOf(value)};
            }
            else if (ckass == Long[].class)
            {
                return new Long[]{Long.valueOf(value)};
            }
            else if (ckass == Boolean[].class)
            {
                return new Boolean[]{Boolean.valueOf(value)};
            }
            else if (ckass == Float[].class)
            {
                return new Float[]{Float.valueOf(value)};
            }
            else if (ckass == Double[].class)
            {
                return new Double[]{Double.valueOf(value)};
            }
            else if (ckass == Character[].class)
            {
                return new Character[]{value.charAt(0)};
            }
            else if (ckass == String[].class)
            {
                return new String[]{value};
            }
            else
            {
                throw new IllegalStateException(name + "这种模式和数组模式不匹配");
            }
        }
        else
        {
            int end   = name.indexOf(']', length);
            int index = Integer.parseInt(name.substring(length + 1, end));
            if (ckass == int[].class)
            {
                int[] array = new int[index + 1];
                array[index] = Integer.parseInt(value);
                return array;
            }
            else if (ckass == byte[].class)
            {
                byte[] array = new byte[index + 1];
                array[index] = Byte.parseByte(value);
                return array;
            }
            else if (ckass == short[].class)
            {
                short[] array = new short[index + 1];
                array[index] = Short.parseShort(value);
                return array;
            }
            else if (ckass == long[].class)
            {
                long[] array = new long[index + 1];
                array[index] = Long.parseLong(value);
                return array;
            }
            else if (ckass == boolean[].class)
            {
                boolean[] array = new boolean[index + 1];
                array[index] = Boolean.parseBoolean(value);
                return array;
            }
            else if (ckass == float[].class)
            {
                float[] array = new float[index + 1];
                array[index] = Float.parseFloat(value);
                return array;
            }
            else if (ckass == double[].class)
            {
                double[] array = new double[index + 1];
                array[index] = Double.parseDouble(value);
                return array;
            }
            else if (ckass == char[].class)
            {
                char[] array = new char[index + 1];
                array[index] = value.charAt(0);
                return array;
            }
            else if (ckass == Integer[].class)
            {
                Integer[] array = new Integer[index + 1];
                array[index] = Integer.valueOf(value);
                return array;
            }
            else if (ckass == Byte[].class)
            {
                Byte[] array = new Byte[index + 1];
                array[index] = Byte.valueOf(value);
                return array;
            }
            else if (ckass == Short[].class)
            {
                Short[] array = new Short[index + 1];
                array[index] = Short.valueOf(value);
                return array;
            }
            else if (ckass == Long[].class)
            {
                Long[] array = new Long[index + 1];
                array[index] = Long.valueOf(value);
                return array;
            }
            else if (ckass == Boolean[].class)
            {
                Boolean[] array = new Boolean[index + 1];
                array[index] = Boolean.valueOf(value);
                return array;
            }
            else if (ckass == Float[].class)
            {
                Float[] array = new Float[index + 1];
                array[index] = Float.valueOf(value);
                return array;
            }
            else if (ckass == Double[].class)
            {
                Double[] array = new Double[index + 1];
                array[index] = Double.valueOf(value);
                return array;
            }
            else if (ckass == Character[].class)
            {
                Character[] array = new Character[index + 1];
                array[index] = value.charAt(0);
                return array;
            }
            else if (ckass == String[].class)
            {
                String[] array = new String[index + 1];
                array[index] = value;
                return array;
            }
            else
            {
                try
                {
                    Object[] array = (Object[]) Array.newInstance(ckass.getComponentType(), index + 1);
                    generateArrayElement(name.substring(end + 1), value, index, array);
                    return array;
                }
                catch (Exception e)
                {
                    ReflectUtil.throwException(e);
                    return null;
                }
            }
        }
    }

    private void generateArrayElement(String subName, String value, int index, Object[] array)
    {
        ContainerBinder nestBinder = this.nestBinder;
        if (nestBinder == null)
        {
            if (ckass.getComponentType().isArray())
            {
                this.nestBinder = nestBinder = new ArrayBinder2("", ckass.getComponentType());
            }
            else if (List.class.isAssignableFrom(ckass.getComponentType()))
            {
                ;
            }
            else
            {
                this.nestBinder = nestBinder = new BeanBinder2("", ckass.getComponentType());
            }
        }
        Object element = nestBinder.bind(subName, value, array[index]);
        array[index] = element;
    }
}
